//"""MLBERTMGR CSharp programmer's guide"""
//__version__     = "1.7.4"
//__author__      = "MultilaneInc <support@multilaneinc.com>"
//__date__        = '2025-11-06'

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
namespace MLBERT
{
    class programmer_guide
    {
        [SecurityCritical]
        static void Main(string[] args)
        {

            mlbertmgr MLBERT = new mlbertmgr();
            bool APPLYCONFIG = true;
            try
            {
                const int NB_CHANNELS = 4;
                int CHANNEL = 4;
                string IPADDRESS = "172.16.171.200";
                // Connects to device before initializing the instance
                Console.WriteLine("mlbertmgr_openConnection status: " + MLBERT.mlbertmgr_openConnection(IPADDRESS));
                // Initialises instance 


                InstanceParams T_PARAMS = new InstanceParams();
                T_PARAMS.saveConfig = "";
                T_PARAMS.saveBathtub = "";
                T_PARAMS.saveEye = "";
                T_PARAMS.saveEyeEnable = 0;
                T_PARAMS.saveBathtubEnable = 0;


                Console.WriteLine("InitializeInstance: " + MLBERT.mlbertmgr_initializeInstance(T_PARAMS));

                MLBERT.mlbertmgr_enableMonitor(0); //Turn off all monitor flags

                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //test flow 1: Get Board information of any BERT

                Board_Info INFO = new Board_Info();
                Console.WriteLine("mlbertmgr_getInfo status: " + MLBERT.mlbertmgr_getInfo(ref INFO));
                Console.WriteLine("Board Info is:");
                Console.WriteLine("\tboardID: " + INFO.boardID);
                Console.WriteLine("\tHWRev: " + INFO.HWRev / 256 + "." + INFO.HWRev % 256);
                Console.WriteLine("\tFWRev: " + INFO.FWRev / 256 + "." + INFO.FWRev % 256);
                Console.WriteLine("\tSilabRev: " + INFO.SilabRev);
                Console.WriteLine("\tipAddress: " + ((INFO.ipAddress >> 24) & 0xff) + "." + ((INFO.ipAddress >> 16) & 0xff) + "." + ((INFO.ipAddress >> 8) & 0xff) + "." + (INFO.ipAddress & 0xff));
                Console.WriteLine("\tMask: " + ((INFO.Mask >> 24) & 0xff) + "." + ((INFO.Mask >> 16) & 0xff) + "." + ((INFO.Mask >> 8) & 0xff) + "." + (INFO.Mask & 0xff));
                Console.WriteLine("\tGateway: " + ((INFO.Gateway >> 24) & 0xff) + "." + ((INFO.Gateway >> 16) & 0xff) + "." + ((INFO.Gateway >> 8) & 0xff) + "." + (INFO.Gateway & 0xff));

                Console.WriteLine("\tMAC: {0:X}-{1:X}-{2:X}-{3:X}-{4:X}-{5:X}", ((INFO.MAC >> 40) & 0xff), ((INFO.MAC >> 32) & 0xff), ((INFO.MAC >> 24) & 0xff), ((INFO.MAC >> 16) & 0xff), ((INFO.MAC >> 8) & 0xff), (INFO.MAC & 0xff));
                Console.Write("\tSN: ");
                for (int i = 0; i < 10; i++)
                {
                    Console.Write("{0:X} ", INFO.SN[i]);
                }
                Console.WriteLine("");


                Console.WriteLine("\tBootloader_Flag: " + INFO.Bootloader_Flag);
                Console.WriteLine("\tisAdapterMode: " + INFO.isAdapterMode);
                if (INFO.isAdapterMode == true) { Console.WriteLine("\tadapterType: " + INFO.adapterType); }


                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //test flow 2:Configure Clock Settings
                //Clock Source
                BERTMGR_CLOCKSOURCE CLOCKSOURCE = BERTMGR_CLOCKSOURCE.BERTMGR_INTERNALCLKSRC;
                // Clock mode        
                BERTMGR_CLOCKMODE CLOCKMODE = BERTMGR_CLOCKMODE.BERTMGR_MONITORCLOCK_CH0toCH3;
                // Monitor Divider                 
                BERTMGR_MONITORDIVIDER DIVIDER = BERTMGR_MONITORDIVIDER.BERTMGR_MONITOR_DIV8;
                //  CDR Divider
                BERTMGR_CDRDIVIDER CDRDIVIDER = BERTMGR_CDRDIVIDER.BERTMGR_CDR_DIV64;

                // Set ClockMode
                //Console.WriteLine("clock mode status: " + MLBERT.mlbertmgr_setClockMode(CLOCKMODE, APPLYCONFIG));

                // Clock Divider
                // Set Monitor Divider
                Console.WriteLine("Monitor devider status " + MLBERT.mlbertmgr_setMonitorDivider(DIVIDER, APPLYCONFIG));

                // set CDR Divider
                // Console.WriteLine("CDR deviderstatus: " + MLBERT.mlbertmgr_setCDRDivider(CDRDIVIDER));


                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //test flow 3: Configure LineRate, Coding and Amplitude Levels

                // Eye Mode
                BERTMGR_SIGMODULATION EYEMODE = BERTMGR_SIGMODULATION.BERTMGR_PAM4;
                // Taps Mode
                BERTMGR_TAPSMODE TAPSMODE = BERTMGR_TAPSMODE.BERTMGR_3TAPS;

                // Line Rate in Gb/s
                double LINERATE = 26.5625;

                // Creates PatternConfig initial struct
                PatternConfig TXPATTERN = new PatternConfig();
                // Tx Pattern                                       
                TXPATTERN.pattern = BERTMGR_PATTERNTYPE.BERTMGR_PRBS7;
                // Tx Invert 
                TXPATTERN.invert = false;
                // Creates PatternConfig initial struct
                PatternConfig RXPATTERN = new PatternConfig();
                // Rx Pattern  
                RXPATTERN.pattern = BERTMGR_PATTERNTYPE.BERTMGR_PRBS7;
                // Tx Invert
                RXPATTERN.invert = false;
                /*
                //user defigned pattern
                //Tx Pattern
                TXPATTERN.pattern = BERTMGR_PATTERNTYPE.BERTMGR_USERDEFINED;
                UserDefinedPatternDefinition USER_DEFIGNED_PATTERN;
                USER_DEFIGNED_PATTERN.Pattern1.Pattern = 0XAAAAFFFF55550000;
                USER_DEFIGNED_PATTERN.Pattern1.Repetition = 1;
                USER_DEFIGNED_PATTERN.Pattern2.Pattern = 0XFFFF0000FFFF0000;
                USER_DEFIGNED_PATTERN.Pattern2.Repetition = 1;
                */
                // Amplitude Level mV
                int AMPLITUDE = 200;

                // Gray Coding Enable
                bool ENABLE = false;

                //fec configuration
                BERTMGR_FECMODE FECMODE = BERTMGR_FECMODE.BERTMGR_FECDISABLED;
                BERTMGR_FECPATTERN FECPATTERN = BERTMGR_FECPATTERN.BERTMGR_FECPATTERN_DISABLED;



                // Set Linerate
                Console.WriteLine("mlbertmgr_setLinerate status: " + MLBERT.mlbertmgr_setLinerate(LINERATE, APPLYCONFIG));

                // set EyeMode                                                      
                Console.WriteLine("mlbertmgr_setEyeMode status: " + MLBERT.mlbertmgr_setEyeMode(EYEMODE, APPLYCONFIG));

                //Enable Gray Coding.Applied for PAM4 Eye Mode                             
                //Console.WriteLine("mlbertmgr_setGrayCoding status: " + MLBERT.mlbertmgr_setGrayCoding(ENABLE, APPLYCONFIG));

                APPLYCONFIG = true;
                // Set Taps Mode                                  
                Console.WriteLine("mlbertmgr_setTapsMode status: " + MLBERT.mlbertmgr_setTapsMode(TAPSMODE, APPLYCONFIG));

                //Set FEC Mode.Check The table of features for compatibility                                           
                //Console.WriteLine("mlbertmgr_setFECMode status: " + MLBERT.mlbertmgr_setFECMode(FECMODE, FECPATTERN, APPLYCONFIG));


                for (int channel = 0; channel < NB_CHANNELS; channel++)
                {

                    // Set Tx Pattern For All Channels                                
                    Console.WriteLine("mlbertmgr_setTxPattern status: " + MLBERT.mlbertmgr_setTxPattern(channel, TXPATTERN, APPLYCONFIG));

                    // Set Rx Pattern For All Channels
                    Console.WriteLine("mlbertmgr_setRxPattern status: " + MLBERT.mlbertmgr_setRxPattern(channel, RXPATTERN, APPLYCONFIG));

                    //set User Defined Pattern 
                    //Console.WriteLine("mlbertmgr_setUserDefinedPattern: " + MLBERT.mlbertmgr_setUserDefinedPattern(channel, USER_DEFIGNED_PATTERN, APPLYCONFIG));

                    //Set Calibrated Amplitude level. This function requires a calibrated Instrument
                    //Console.WriteLine("mlbertmgr_setAmplitude status: " + MLBERT.mlbertmgr_setAmplitude(channel, AMPLITUDE, APPLYCONFIG));
                }



                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test flow 4: Set advanced amplitude and equalization

                // Advanced Amplitude
                AdvancedAmplitude ADVANCEDAMPLITUDE = new AdvancedAmplitude();
                // Main Tap Value(-1000 to + 1000)
                ADVANCEDAMPLITUDE.mainTap = 350;
                // Post - emphasis Value(-1000 to + 1000)
                ADVANCEDAMPLITUDE.preEmphasis = -50;
                // Pre-emphasis Value (-1000 to +1000)
                ADVANCEDAMPLITUDE.postEmphasis = -50;
                // Inner Eye level(500 to 1500).Applied for PAM4
                ADVANCEDAMPLITUDE.innerLevel = 1000;
                // Outer Eye level (1500 to 2500). Applied to PAM4
                ADVANCEDAMPLITUDE.outerLevel = 2000;
                // Scaling Level Percentage (70, 80, 90, 100, 110, 120)
                ADVANCEDAMPLITUDE.scalingLevel = 80;
                // 7-Taps Mode
                ADVANCEDAMPLITUDE.advancedTaps = new int[7] { 0, 0, 0, 0, 0, 0, 0 };
                //APROX AMPLITUDE
                int APROXAMPLITUDE = 0;
                bool ISENABLED = false;
                BERTMGR_DSPMODE DSPMODE = BERTMGR_DSPMODE.BERTMGR_DSP_MODE_SLC1;

                for (int channels = 0; channels < NB_CHANNELS; channels++)
                {

                    //# Set Rx DSP MODE - optional
                    //Console.WriteLine("mlbertmgr_setAdvancedAmplitude status: " + MLBERT.mlbertmgr_setDSPMode(CHANNELS, DSPMODE, APPLYCONFIG));


                    //set advanced amplitude
                    Console.WriteLine("mlbertmgr_setAdvancedAmplitude status: " + MLBERT.mlbertmgr_setAdvancedAmplitude(channels, ADVANCEDAMPLITUDE, ref APROXAMPLITUDE, APPLYCONFIG));
                    Console.WriteLine("APROXAMPLITUDE: " + APROXAMPLITUDE);
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////////
                //// Test Flow 5: Enable – disable RX, TX
                for (int channels = 0; channels < NB_CHANNELS; channels++)
                {
                    // Enable All RX Channel
                    Console.WriteLine("mlbertmgr_RxEnable status: " + MLBERT.mlbertmgr_RxEnable(channels, true));

                    // Read All RX Status                         
                    ISENABLED = false;

                    Console.WriteLine("isenabledertmgr_getRxStatus status: " + MLBERT.mlbertmgr_getRxStatus(channels, ref ISENABLED));
                    Console.WriteLine("Rx Status: " + ISENABLED);

                    // Enable All TX Channel
                    Console.WriteLine("mlbertmgr_TxEnable status: " + MLBERT.mlbertmgr_TxEnable(channels, true));

                    // Read All RX Status 
                    ISENABLED = false;
                    Console.WriteLine("isenabledertmgr_getTxStatus status: " + MLBERT.mlbertmgr_getTxStatus(channels, ref ISENABLED));
                    Console.WriteLine("Tx Status: " + channels + " " + ISENABLED);
                }

                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test flow 6:Get Active Configuration Settings


                ConfigurationSettings CONFIG = new ConfigurationSettings();
                //Console.WriteLine("mlbertmgr_getActiveConfig status: " + MLBERT.mlbertmgr_getActiveConfig(ref CONFIG));
                Console.WriteLine("linerate: " + CONFIG.linerate);

                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test flow 5: Monitor function

                // First method : Single read monitor flags.
                // Reads BERT Temperature flags
                BERTMGR_MONITOR_FLAGS SINGLEMONITORFLAG = BERTMGR_MONITOR_FLAGS.BERTMGR_MONITOR_TEMPERATURE;

                //Temperature monitor requires 4 x ushort.Refer to the documentation for the required memory allocation per flag
                ushort[] SINGLE_MONITOR = new ushort[NB_CHANNELS];
                // Enable Single Monitor Flag and sleep for 350 ms before starting monitor reading.
                // It is recommended to Enable the Monitor at the beginning of the main flow to avoid any settling time.
                // Enable Single Monitor Flag
                bool ENABLED = true;//PYTHON CHANGE
                Console.WriteLine("mlbertmgr_enableMonitorFlag status:" + MLBERT.mlbertmgr_enableMonitorFlag(SINGLEMONITORFLAG, ENABLED));

                // Single Read Monitor Flag
                Console.WriteLine("mlbertmgr_singleReadMonitor status:" + MLBERT.mlbertmgr_singleReadMonitor(SINGLEMONITORFLAG, SINGLE_MONITOR));
                Thread.Sleep(350);

                //Disable Single Monitor Flag
                ENABLED = false;
                Console.WriteLine("mlbertmgr_enableMonitorFlag status:" + MLBERT.mlbertmgr_enableMonitorFlag(SINGLEMONITORFLAG, ENABLED));

                // Second method : MultiRead monitor flags
                // Refer to MONITOR_FLAGS Enum for bits order.Set to 1023 to enable all monitor flags
                int MULTIMONITORFLAGS = 31;
                // Monitor multiple Flags(e.g 200) following the same order of the MONITOR_FLAGS Enum
                ushort[] MULTI_MONITOR = new ushort[400];
                // Enable Multi Monitor Flags
                Console.WriteLine("mlbertmgr_enableMonitor status : " + MLBERT.mlbertmgr_enableMonitor(MULTIMONITORFLAGS));
                // Multi - Read Monitor
                Console.WriteLine("mlbertmgr_multiReadMonitor status: " + MLBERT.mlbertmgr_multiReadMonitor(MULTIMONITORFLAGS, MULTI_MONITOR));
                // Wait for Monitor Accumulation.
                Thread.Sleep(350);
                // Disable Monitor Flags
                MULTIMONITORFLAGS = 0;               
                Console.WriteLine("mlbertmgr_enableMonitor status: " + MLBERT.mlbertmgr_enableMonitor(MULTIMONITORFLAGS));

                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test Flow 8: Execute fundamental BER Test

                //Pre-allocate MEASBERDATA Struct
                MeasurementsData[] MEASBERDATA = new MeasurementsData[128];
                int DATACOUNT = 0;

                // Enable BER Data Accumulation. Otherwise, the latest Data is captured
                bool ACCUMULATE = false;
                // BER Enbaled CHANNELS. First Channel is Enabled
                ushort BERENABLEDCH = 0;
                for (int i = 0; i < NB_CHANNELS; i++)
                {
                    BERENABLEDCH = (ushort)(BERENABLEDCH + (1 << i));
                }
                Console.WriteLine("BERENABLEDCH " + BERENABLEDCH);
                ushort[] VALUE = new ushort[NB_CHANNELS];

                // Before starting the BER accumulation, it is recommended to add a settling time of 2 seconds
                // ML4054B requires 4 seconds after the configuration
                // "pymlbertmgr.getConfigStatus()" will be implemented in a future library release to check the instrument configuration status and avoid adding a sleep time in the application script
                Thread.Sleep(1000);  //  For ML4079EN use 10000
                // Initialize Rx Lock Status and Monitor Rx Lock Status


                // initialize Rx Lock Monitor Flag
                SINGLEMONITORFLAG = BERTMGR_MONITOR_FLAGS.BERTMGR_MONITOR_RXLOCK;


                Console.WriteLine("mlbertmgr_enableMonitorFlag status: " + MLBERT.mlbertmgr_enableMonitorFlag(SINGLEMONITORFLAG, true));
                Thread.Sleep(100);    // Sleep for 100 ms


                for (int channels = 0; channels < NB_CHANNELS; channels++)
                {   // Call Rx lock Status in a while loop
                    int RETRY = 7;
                    while (VALUE[channels] == 0 && RETRY > 0)
                    {

                        MLBERT.mlbertmgr_singleReadMonitor(SINGLEMONITORFLAG, VALUE);
                        Thread.Sleep(350);
                        RETRY -= 1;
                    }
                    Console.WriteLine("Rx " + channels + ((VALUE[channels] == 1) ? " is  locked!" : " is not locked!"));
                }

                // Disable Monitor Flags
                Console.WriteLine("mlbertmgr_enableMonitorFlag status: " + MLBERT.mlbertmgr_enableMonitorFlag(SINGLEMONITORFLAG, false));
                Thread.Sleep(350);


                // Start BER. This function requires Rx Lock.
                MLBERT.mlbertmgr_startBER(BERENABLEDCH, ACCUMULATE);
                Console.WriteLine("start BER ");
                // BER Counting Time
                // ML4054 BER Accumulation starts 4 seconds after enabling the BER process.
                Thread.Sleep(4000);
                DATACOUNT = MLBERT.mlbertmgr_getAvailableBERData(ref MEASBERDATA);
                //Get Available Data
                Console.WriteLine("mlbertmgr_getAvailableBERData Data Count: " + DATACOUNT);
                //print Out BER Data. Check MeasurementsData struct for more details                
                Console.WriteLine("Measured BER Data : ");

                Console.WriteLine("\tIs BER Enabled : " + MEASBERDATA[DATACOUNT - 1].berData.IsEnabled);
                for (int channel = 0; channel < NB_CHANNELS; channel++)
                {

                    Console.WriteLine("channel: " + channel);
                    Console.WriteLine("\tEnabled Channels :" + MEASBERDATA[DATACOUNT - 1].berData.enabledChannels[channel]);
                    Console.WriteLine("\tLocked Channels : " + MEASBERDATA[DATACOUNT - 1].berData.lockedChannels[channel]);
                    Console.WriteLine("\tBER Capture Time : " + MEASBERDATA[DATACOUNT - 1].berData.Time[channel]);
                    Console.WriteLine("\tBit Count : " + MEASBERDATA[DATACOUNT - 1].berData.BitCount[channel]);
                    Console.WriteLine("\tErrorCount_MSB  :" + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount_MSB[channel]);
                    Console.WriteLine("\tErrorCount_LSB  :" + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount_LSB[channel]);
                    Console.WriteLine("\tErrorCount  :" + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount[channel]);
                    Console.WriteLine("\tAccumulatedErrorCount_MSB  :" + MEASBERDATA[DATACOUNT - 1].berData.AccumulatedErrorCount_MSB[channel]);
                    Console.WriteLine("\ttBER_MSB_Interval : " + MEASBERDATA[DATACOUNT - 1].berData.BER_MSB_Interval[channel]);
                    Console.WriteLine("\tBER_MSB_Realtime  :" + MEASBERDATA[DATACOUNT - 1].berData.BER_MSB_Realtime[channel]);
                    Console.WriteLine("\tAccumulatedErrorCount_LSB  :" + MEASBERDATA[DATACOUNT - 1].berData.AccumulatedErrorCount_LSB[channel]);
                    Console.WriteLine("\tBER_LSB_Interval  :" + MEASBERDATA[DATACOUNT - 1].berData.BER_LSB_Interval[channel]);
                    Console.WriteLine("\tBER_LSB_Realtime  :" + MEASBERDATA[DATACOUNT - 1].berData.BER_LSB_Realtime[channel]);
                    Console.WriteLine("\tAccumulatedErrorCount  :" + MEASBERDATA[DATACOUNT - 1].berData.AccumulatedErrorCount[channel]);
                    Console.WriteLine("\tBER_MSB_Interval : " + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount[channel]);
                    Console.WriteLine("\tBER Realtime : " + MEASBERDATA[DATACOUNT - 1].berData.BER_Realtime[channel]);
                }
                //MLBERT.mlbertmgr_stopBER();

                //MLBERT.mlbertmgr_startBER(BERENABLEDCH, ACCUMULATE);
                Console.WriteLine("start BER ");
                // BER Counting Time
                // ML4054 BER Accumulation starts 4 seconds after enabling the BER process.
                Thread.Sleep(4000);

                DATACOUNT = MLBERT.mlbertmgr_getAvailableBERData(ref MEASBERDATA);
                //Get Available Data
                Console.WriteLine("mlbertmgr_getAvailableBERData Data Count: " + DATACOUNT);
                //print Out BER Data. Check MeasurementsData struct for more details                
                Console.WriteLine("Measured BER Data : ");

                Console.WriteLine("\tIs BER Enabled : " + MEASBERDATA[DATACOUNT - 1].berData.IsEnabled);
                for (int channel = 0; channel < NB_CHANNELS; channel++)
                {

                    Console.WriteLine("channel: " + channel);
                    Console.WriteLine("\tEnabled Channels :" + MEASBERDATA[DATACOUNT - 1].berData.enabledChannels[channel]);
                    Console.WriteLine("\tLocked Channels : " + MEASBERDATA[DATACOUNT - 1].berData.lockedChannels[channel]);
                    Console.WriteLine("\tBER Capture Time : " + MEASBERDATA[DATACOUNT - 1].berData.Time[channel]);
                    Console.WriteLine("\tBit Count : " + MEASBERDATA[DATACOUNT - 1].berData.BitCount[channel]);
                    Console.WriteLine("\tErrorCount_MSB  :" + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount_MSB[channel]);
                    Console.WriteLine("\tErrorCount_LSB  :" + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount_LSB[channel]);
                    Console.WriteLine("\tErrorCount  :" + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount[channel]);
                    Console.WriteLine("\tAccumulatedErrorCount_MSB  :" + MEASBERDATA[DATACOUNT - 1].berData.AccumulatedErrorCount_MSB[channel]);
                    Console.WriteLine("\ttBER_MSB_Interval : " + MEASBERDATA[DATACOUNT - 1].berData.BER_MSB_Interval[channel]);
                    Console.WriteLine("\tBER_MSB_Realtime  :" + MEASBERDATA[DATACOUNT - 1].berData.BER_MSB_Realtime[channel]);
                    Console.WriteLine("\tAccumulatedErrorCount_LSB  :" + MEASBERDATA[DATACOUNT - 1].berData.AccumulatedErrorCount_LSB[channel]);
                    Console.WriteLine("\tBER_LSB_Interval  :" + MEASBERDATA[DATACOUNT - 1].berData.BER_LSB_Interval[channel]);
                    Console.WriteLine("\tBER_LSB_Realtime  :" + MEASBERDATA[DATACOUNT - 1].berData.BER_LSB_Realtime[channel]);
                    Console.WriteLine("\tAccumulatedErrorCount  :" + MEASBERDATA[DATACOUNT - 1].berData.AccumulatedErrorCount[channel]);
                    Console.WriteLine("\tBER_MSB_Interval : " + MEASBERDATA[DATACOUNT - 1].berData.ErrorCount[channel]);
                    Console.WriteLine("\tBER Realtime : " + MEASBERDATA[DATACOUNT - 1].berData.BER_Realtime[channel]);
                }


                // Stop BER 
                MLBERT.mlbertmgr_stopBER();

                //////////////////////////////////////////////////////////////////////////////////////////////////////
                // Test Flow 9: Read Histogram Data

                //Edit parameters for your instance
                //Enabled channel flags(1 bit / channel)
                ushort HISTENABLEDCHANNEL = 1 << 4;

                HistogramData[] HIST = new HistogramData[8];
                //Get Enabled Channels
                ushort ACTUAL_ENABLED = 0;

                //blocking API call
                Console.WriteLine("mlbertmgr_captureHistogramData status: " + MLBERT.mlbertmgr_getHistogramData(HISTENABLEDCHANNEL, HIST));

                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test Flow 10: FEC Mode
                //fec configuration

                FECMODE = BERTMGR_FECMODE.BERTMGR_400G_KP8_TO_KP4;
                FECPATTERN = BERTMGR_FECPATTERN.BERTMGR_FECPATTERN_IDLE;
                ushort CHANNELS = 255;

                //Set FEC Mode.Check The table of features for compatibility                                           
                //Console.WriteLine("mlbertmgr_setFECMode status: " + MLBERT.mlbertmgr_setFECMode(FECMODE, FECPATTERN, APPLYCONFIG));
                APPLYCONFIG = true;
                Console.WriteLine("mlbertmgr_configureFECLinks status: " + MLBERT.mlbertmgr_configureFECLinks(CHANNELS, APPLYCONFIG));
                Thread.Sleep(4000);

                // Start BER. This function requires Rx Lock.
                MLBERT.mlbertmgr_startBER(BERENABLEDCH, ACCUMULATE);
                Console.WriteLine("start BER ");
                // BER Counting Time
                // ML4054 BER Accumulation starts 4 seconds after enabling the BER process.
                Thread.Sleep(4000);
                DATACOUNT = MLBERT.mlbertmgr_getAvailableBERData(ref MEASBERDATA);
                //Get Available Data
                Console.WriteLine("mlbertmgr_getAvailableBERData Datacount: " + DATACOUNT);
                //print Out BER Data. Check MeasurementsData struct for more details
                Console.WriteLine("Measured BER Data : ");

                //Console.WriteLine("\tIs BER Enabled : " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.enabled);
                //for (int channel = 0; channel < 8; channel++)
                //{

                //    Console.WriteLine("channel: " + channel);
                //    Console.WriteLine("\tenabled Links: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.enabledLinks[channel]);
                //    Console.WriteLine("\tlocked Links: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.lockedLinks[channel]);
                //    Console.WriteLine("\tBER Capture Time: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.Time[channel]);
                //    Console.WriteLine("\tBit Count: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.BitCount[channel]);
                //    Console.WriteLine("\tFEC Corrected Bit Count Interval: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.FEC_CorrectedBitCount_Interval[channel]);
                //    Console.WriteLine("\tFEC CW UnCorrected Count Interval: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.FEC_CW_UnCorrectedCount_Interval[channel]);
                //    Console.WriteLine("\tFEC CW Corrected Count Interval: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.FEC_CW_CorrectedCount_Interval[channel]);
                //    Console.WriteLine("\tFEC CW ProcessedCount Interval: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.FEC_CW_ProcessedCount_Interval[channel]);
                //    Console.WriteLine("\tFEC_CW_UncorrectedErrorRate_Interval: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.FEC_CW_UncorrectedErrorRate_Interval[channel]);
                //    Console.WriteLine("\tAccumulated FEC CW UnCorrected Count: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.AccumulatedFEC_CW_UnCorrectedCount[channel]);
                //    Console.WriteLine("\tAccumulated FEC CW Corrected Count: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.AccumulatedFEC_CW_CorrectedCount[channel]);
                //    Console.WriteLine("\tAccumulated FEC CW Processed Count: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.AccumulatedFEC_CW_ProcessedCount[channel]);
                //    Console.WriteLine("\tAccumulated FEC CW Uncorrected Error Rate: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.AccumulatedFEC_CW_UncorrectedErrorRate[channel]);
                //    Console.WriteLine("\tSER nSymbols: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.SER[channel].nSymbols);
                //    Console.WriteLine("\tInstantSER: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.SER[channel].InstantSER[0]);
                //    Console.WriteLine("\tAccumulatedSER: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.SER[channel].AccumulatedSER[0]);
                //    Console.WriteLine("\tBER_MSB_Interval: " + MEASBERDATA[DATACOUNT - 1].realFECData_4044.TotalBitCount[channel]);


                //}

                // Stop BER 
                MLBERT.mlbertmgr_stopBER();





                // Detect Module Adapter Type 
                //ADAPTER_TYPE ADAPTERTYPE = 0;
                //Console.WriteLine("mlbertmgr_detectAdapter status: " + MLBERT.mlbertmgr_detectAdapter(ref ADAPTERTYPE));
                //Console.WriteLine("Adapter Type = " + ADAPTERTYPE);

                //// Set Adapter I2C Control Mode to External
                //ISENABLED = false;
                //Console.WriteLine("mlbertmgr_setExternalAdapterMode status: " + MLBERT.mlbertmgr_setExternalAdapterMode(ISENABLED));
                //Console.WriteLine("External Adapter Mode set to: " + ISENABLED);

                //// Control Adapter Pins
                //bool STATUS = false;
                //ADAPTER_HWSIGNAL_CNTRL AdapterContolePin = ADAPTER_HWSIGNAL_CNTRL.ADAPTER_HWSIGNAL_CNTRL_QDD_MODSEL_L;
                //Console.WriteLine("mlbertmgr_setControlPin status:  " + MLBERT.mlbertmgr_setControlPin(AdapterContolePin, STATUS));

                ////////////////////////////////////////////////////////////////////////////////////////////////////////
                ////Test Flow 11: Tranceiver control Flow
                ////SetTXOutputDisable
                //CHANNEL = 0;
                //STATUS = true;

                ////Transceiver TX Output Disable
                //Console.WriteLine("mltxvr_setTXOutputDisable status: " + MLBERT.mltxvr_setTxOutputDisable(CHANNEL, STATUS));

                //// Transceiver DataPathDeInit Configuration.
                //Console.WriteLine("mltxvr_setTXDataPathDeInit status: " + MLBERT.mltxvr_setTxDataPathDeInit(CHANNEL, STATUS));

                //// Transceiver TX Squelch Disable Configuration.
                //Console.WriteLine("mltxvr_setTXSquelchDisable status: " + MLBERT.mltxvr_setTxSquelchDisable(CHANNEL, STATUS));

                ////Transceiver TX Force Squelch Configuration.
                //Console.WriteLine("mltxvr_setTXForceSquelch status: " + MLBERT.mltxvr_setTxForceSquelch(CHANNEL, STATUS));

                ////Transceiver TX Polarity Flip Configuration.
                //Console.WriteLine("mltxvr_setTXPolarityFlip status: " + MLBERT.mltxvr_setTxPolarityFlip(CHANNEL, STATUS));

                //// Transceiver TX input equalization
                //// CMIS Range is from 0 - 12.
                //int I_VALUE = 1;
                //Console.WriteLine("mltxvr_setTXInputEqualization status: " + MLBERT.mltxvr_setTxInputEqualization(CHANNEL, I_VALUE));

                ////Transceiver RX Controls
                //STATUS = true;
                //// Transceiver Rx Polarity Flip
                //Console.WriteLine("mltxvr_setRXPolarityFlip status: " + MLBERT.mltxvr_setRxPolarityFlip(CHANNEL, STATUS));

                //// Transceiver RX Squelch Disable Configuration.
                //Console.WriteLine("mltxvr_setRXSquelchDisable status: " + MLBERT.mltxvr_setRxSquelchDisable(CHANNEL, STATUS));

                ////Transceiver RX Output Disable Configuration.
                //Console.WriteLine("mltxvr_setRXOutputDisable status: " + MLBERT.mltxvr_setRxOutputDisable(CHANNEL, STATUS));

                //// Transceiver RX Output Pre - Cursor.
                //// CMIS Range from 0 - 7
                //I_VALUE = 1;
                //Console.WriteLine("mltxvr_setRXPreCursor status: " + MLBERT.mltxvr_setRxPreCursor(CHANNEL, I_VALUE));

                //// Transceiver RX Output Post - Cursor.
                //// Range from 0 - 7
                //Console.WriteLine("mltxvr_setRXPostCursor status: " + MLBERT.mltxvr_setRxPostCursor(CHANNEL, I_VALUE));

                //// Transceiver RX Output Amplitude.
                //TXVR_RX_AMPLITUDE TRANS_RX_AMPLITUDE = TXVR_RX_AMPLITUDE.TXVR_RX_AMPLITUDE_100_400;
                //Console.WriteLine("mltxvr_setRXAmplitude status: " + MLBERT.mltxvr_setRxAmplitude(CHANNEL, TRANS_RX_AMPLITUDE));

                //TXVR_ConfigurationSettings TRANS_ACTIVECONFIG = new TXVR_ConfigurationSettings();
                //int TRANS_NB_CHANNEL = 8;
                //Console.WriteLine("mltxvr_getActiveConfig status: " + MLBERT.mltxvr_getActiveConfig(ref TRANS_ACTIVECONFIG));
                //for (int channels = 0; channels < TRANS_NB_CHANNEL; channels++)
                //{
                //    Console.WriteLine("channel: " + channels);
                //    Console.WriteLine("\tDataPathDeInit: " + TRANS_ACTIVECONFIG.DataPathDeInit[channels]);
                //    Console.WriteLine("\tTXOuputDisable: " + TRANS_ACTIVECONFIG.TXOuputDisable[channels]);
                //    Console.WriteLine("\tTXPolarityFlip: " + TRANS_ACTIVECONFIG.TXPolarityFlip[channels]);
                //    Console.WriteLine("\tTXSquelchDisable: " + TRANS_ACTIVECONFIG.TXSquelchDisable[channels]);
                //    Console.WriteLine("\tTXForceSquelch: " + TRANS_ACTIVECONFIG.TXForceSquelch[channels]);
                //    Console.WriteLine("\tTXEqualization: " + TRANS_ACTIVECONFIG.TXEqualization[channels]);
                //    Console.WriteLine("\tRXOutputDisable: " + TRANS_ACTIVECONFIG.RXOutputDisable[channels]);
                //    Console.WriteLine("\tRXPolarityFlip: " + TRANS_ACTIVECONFIG.RXPolarityFlip[channels]);
                //    Console.WriteLine("\tRXSquelchDisable: " + TRANS_ACTIVECONFIG.RXSquelchDisable[channels]);
                //    Console.WriteLine("\tRXOutputAmplitude: " + TRANS_ACTIVECONFIG.RXOutputAmplitude[channels]);
                //    Console.WriteLine("\tRXOutputPreCursor: " + TRANS_ACTIVECONFIG.RXOutputPreCursor[channels]);
                //    Console.WriteLine("\tRXOutputPostCursor: " + TRANS_ACTIVECONFIG.RXOutputPostCursor[channels]);

                //}
                ////  Reads Transceiver MSA values
                //const int NB_PAGES = 7;
                //TXVR_MSA_PAGE[] MSAPAGES = new TXVR_MSA_PAGE[7] {
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_LOWERMEMORY,
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_0 ,
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_1,
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_2,
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_3,
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_16,
                //    TXVR_MSA_PAGE.TXVR_MSA_PAGE_17 };


                //ushort[] MSAVALUES = new ushort[128 * NB_PAGES];
                //Console.WriteLine("mltxvr_getMSAValues status: " + MLBERT.mltxvr_getMSAValues(MSAPAGES, ref MSAVALUES, NB_PAGES));

                ////Sequential MSA Read
                ////Register addresse range is 128->255, Except LOWERMEMORY where the addresse range is 0->127
                ////LOWERMEMORY page index is 0
                //ushort READING_PAGE_SELECT = 0;
                //ushort READING_REGISTER_ADDRESS = 128;
                //const ushort READING_DATA_LENGTH = 128;
                //ushort[] READING_DATA_BUFFER = new ushort[READING_DATA_LENGTH];
                //Console.WriteLine("mltxvr_sequentialRead status: " + MLBERT.mltxvr_sequentialRead(READING_PAGE_SELECT, READING_REGISTER_ADDRESS, READING_DATA_LENGTH, ref READING_DATA_BUFFER, READING_PAGE_SELECT));

                /*
                //Sequential MSA Write
                ushort WRITING_PAGE_SELECT = 0;
                ushort WRITING_REGISTER_ADDRESS = 0;
                const ushort WRITING_DATA_LENGTH = 128;
                ushort []WRITING_DATA_BUFFER= new ushort[READING_DATA_LENGTH];
                ushort WRITING_BANK_SELECT = 0;
                Console.WriteLine("mltxvr_sequentialWrite status: " + MLBERT.mltxvr_sequentialWrite(WRITING_PAGE_SELECT, WRITING_REGISTER_ADDRESS, WRITING_DATA_LENGTH, WRITING_DATA_BUFFER, WRITING_BANK_SELECT));
                */


                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test Flow 12: Adapter And Transceiver Monitor Flow
                // Enable Adapter Monitor Flag
                BERTMGR_MONITOR_FLAGS MONITORFLAG = BERTMGR_MONITOR_FLAGS.BERTMGR_MONITOR_ADAPTER;
                //Monitor Adapter requires 26 ushort values
                ushort[] ADAPTER_MONITOR_VALUES = new ushort[26];

                ENABLED = true;
                Console.WriteLine("mlbertmgr_enableMonitorFlag status: " + MLBERT.mlbertmgr_enableMonitorFlag(MONITORFLAG, ENABLED));
                // Wait for Monitor Accumulation
                Thread.Sleep(350);
                // Single - Read Monitor
                Console.WriteLine("mlbertmgr_singleReadMonitor status: " + MLBERT.mlbertmgr_singleReadMonitor(MONITORFLAG, ADAPTER_MONITOR_VALUES));
                // Disable Monitor
                ENABLED = false;//spelling python
                Console.WriteLine("mlbertmgr_enableMonitorFlag status: " + MLBERT.mlbertmgr_enableMonitorFlag(MONITORFLAG, ENABLED));

                // Print Out Adapter Monitor Values.Voltage values must be converted by dividing by 256
                Console.WriteLine("VCC =  " + (double)ADAPTER_MONITOR_VALUES[0] / 256 + "V");
                Console.WriteLine("VCC1 =  " + (double)ADAPTER_MONITOR_VALUES[1] / 256 + "V");
                Console.WriteLine("VCC-TX =  " + (double)ADAPTER_MONITOR_VALUES[2] / 256 + "V");
                Console.WriteLine("VCC-RX =  " + (double)ADAPTER_MONITOR_VALUES[3] / 256 + "V");
                Console.WriteLine("VOLTAGE5 =  " + ADAPTER_MONITOR_VALUES[4] + "V");
                Console.WriteLine("VOLTAGE6 =  " + ADAPTER_MONITOR_VALUES[5] + "V");
                Console.WriteLine("VOLTAGE7 =  " + ADAPTER_MONITOR_VALUES[6] + "V");
                Console.WriteLine("VOLTAGE8 =  " + ADAPTER_MONITOR_VALUES[7] + "V");
                Console.WriteLine("I-VCC  =  " + ADAPTER_MONITOR_VALUES[8] + "mA");
                Console.WriteLine("I-VCC1  =  " + ADAPTER_MONITOR_VALUES[9] + "mA");
                Console.WriteLine("I-VCC-TX  =  " + ADAPTER_MONITOR_VALUES[10] + "mA");
                Console.WriteLine("I-VCC-RX  =  " + ADAPTER_MONITOR_VALUES[11] + "mA");
                Console.WriteLine("CURRENT5 =  " + ADAPTER_MONITOR_VALUES[12] + "mA");
                Console.WriteLine("CURRENT6 =  " + ADAPTER_MONITOR_VALUES[13] + "mA");
                Console.WriteLine("CURRENT7 =  " + ADAPTER_MONITOR_VALUES[14] + "mA");
                Console.WriteLine("CURRENT8 =  " + ADAPTER_MONITOR_VALUES[15] + "mA");
                Console.WriteLine("Temp1 =  " + ADAPTER_MONITOR_VALUES[16]);
                Console.WriteLine("Temp2 =  " + ADAPTER_MONITOR_VALUES[17]);
                Console.WriteLine("Temp3 =  " + ADAPTER_MONITOR_VALUES[18]);
                Console.WriteLine("Temp4 =  " + ADAPTER_MONITOR_VALUES[19]);
                Console.WriteLine("Temp5 =  " + ADAPTER_MONITOR_VALUES[20]);
                Console.WriteLine("Temp6 =  " + ADAPTER_MONITOR_VALUES[21]);
                Console.WriteLine("Temp7 =  " + ADAPTER_MONITOR_VALUES[22]);
                Console.WriteLine("Temp8 =  " + ADAPTER_MONITOR_VALUES[23]);

                Console.WriteLine("Control Signals: ");
                // Read back control Pins Status
                if ((ADAPTER_MONITOR_VALUES[24] & 1 << 0) == 1 << 0)
                    Console.WriteLine("\tModeSetL is enabled");

                else Console.WriteLine("\tModeSetL is disabled");

                if ((ADAPTER_MONITOR_VALUES[24] & (1 << 1)) == 1 << 1)
                    Console.WriteLine("\tResetL is enabled");

                else Console.WriteLine("\tResetL is disabled");

                if ((ADAPTER_MONITOR_VALUES[24] & 1 << 2) == 1 << 2)
                    Console.WriteLine("\tLPMode is enabled");

                else Console.WriteLine("\tLPMode is disabled");
                Console.WriteLine("RO Signals: ");

                //Active Low
                if ((ADAPTER_MONITOR_VALUES[24] & 1 << 3) != 1 << 3)
                    Console.WriteLine("\tModePrsL is active");

                else Console.WriteLine("\tModePrsL is deactive");

                //Active Low
                if ((ADAPTER_MONITOR_VALUES[24] & 1 << 4) != 1 << 4)
                    Console.WriteLine("\tIntL is active");

                else Console.WriteLine("\tIntL is deactive");
                Console.WriteLine("Adapter IsExternalMode:  " + ADAPTER_MONITOR_VALUES[25]);

                // Enable Transceiver Monitor Flag
                MONITORFLAG = BERTMGR_MONITOR_FLAGS.BERTMGR_MONITOR_TRANSCEIVER;
                // Monitor Transceiver requires ushort values.
                ushort[] TRANS_MONITOR_VALUES = new ushort[80];
                ENABLED = true;
                Console.WriteLine("mlbertmgr_enableMonitorFlag status: " + MLBERT.mlbertmgr_enableMonitorFlag(MONITORFLAG, ENABLED));

                //# Wait for Monitor Accumulation
                Thread.Sleep(350);

                // Single - Read Monitor
                Console.WriteLine("mlbertmgr_singleReadMonitor status: " + MLBERT.mlbertmgr_singleReadMonitor(MONITORFLAG, TRANS_MONITOR_VALUES));
                //# Disable Transceiver Monitor Flag
                ENABLED = false; //check python spelling 
                Console.WriteLine("mlbertmgr_enableMonitorFlag status: " + MLBERT.mlbertmgr_enableMonitorFlag(MONITORFLAG, ENABLED));

                //Conversion is Performed According to CMIS Standard
                Console.WriteLine("tempSupplyFlags:  " + TRANS_MONITOR_VALUES[0]);
                Console.WriteLine("aux1Aux2Flags:  " + TRANS_MONITOR_VALUES[1]);
                Console.WriteLine("aux3VendorFlags:  " + TRANS_MONITOR_VALUES[2]);
                Console.WriteLine("Temp1:  " + (double)TRANS_MONITOR_VALUES[3] / 256);
                Console.WriteLine("Temp2:  " + (double)TRANS_MONITOR_VALUES[4] / 256);
                Console.WriteLine("Temp3:  " + (double)TRANS_MONITOR_VALUES[5] / 256);
                Console.WriteLine("Temp4:  " + (double)TRANS_MONITOR_VALUES[6] / 256);
                Console.WriteLine("VCC:  " + (double)TRANS_MONITOR_VALUES[7] / 10000 + "V");
                Console.WriteLine("VCC2:  " + (double)TRANS_MONITOR_VALUES[8] / 10000 + "V");
                Console.WriteLine("VCC3:  " + (double)TRANS_MONITOR_VALUES[9] / 10000 + "V");
                Console.WriteLine("VCC4:  " + (double)TRANS_MONITOR_VALUES[10] / 10000 + "V");
                Console.WriteLine("aux1:  " + TRANS_MONITOR_VALUES[11]);
                Console.WriteLine("aux2:  " + TRANS_MONITOR_VALUES[12]);
                Console.WriteLine("aux3:  " + TRANS_MONITOR_VALUES[13]);
                Console.WriteLine("STATE_CHANGE:  " + TRANS_MONITOR_VALUES[14]);
                Console.WriteLine("TX_FAULT:  " + TRANS_MONITOR_VALUES[15]);
                Console.WriteLine("TX_LOS:  " + TRANS_MONITOR_VALUES[16]);
                Console.WriteLine("TX_LOL:  " + TRANS_MONITOR_VALUES[17]);
                Console.WriteLine("TXPOWER_HA:  " + TRANS_MONITOR_VALUES[18]);
                Console.WriteLine("TXPOWER_LA:  " + TRANS_MONITOR_VALUES[19]);
                Console.WriteLine("TXPOWER_HW:  " + TRANS_MONITOR_VALUES[20]);
                Console.WriteLine("TXPOWER_LW:  " + TRANS_MONITOR_VALUES[21]);
                Console.WriteLine("TXBIAS_HA:  " + TRANS_MONITOR_VALUES[22]);
                Console.WriteLine("TXBIAS_LA:  " + TRANS_MONITOR_VALUES[23]);
                Console.WriteLine("TXBIAS_HW:  " + TRANS_MONITOR_VALUES[24]);
                Console.WriteLine("TXBIAS_LW:  " + TRANS_MONITOR_VALUES[25]);
                Console.WriteLine("RX_LOS:  " + TRANS_MONITOR_VALUES[26]);
                Console.WriteLine("RX_LOL:  " + TRANS_MONITOR_VALUES[27]);
                Console.WriteLine("RXPOWER_HA:  " + TRANS_MONITOR_VALUES[28]);
                Console.WriteLine("RXPOWER_LA:  " + TRANS_MONITOR_VALUES[29]);
                Console.WriteLine("RXPOWER_LW:  " + TRANS_MONITOR_VALUES[30]);
                Console.WriteLine("RXPOWER_LW:  " + TRANS_MONITOR_VALUES[31]);
                Console.WriteLine("TX0:  " + (double)TRANS_MONITOR_VALUES[32] / 10000 + "mW");
                Console.WriteLine("TX1:  " + (double)TRANS_MONITOR_VALUES[33] / 10000 + "mW");
                Console.WriteLine("TX2:  " + (double)TRANS_MONITOR_VALUES[34] / 10000 + "mW");
                Console.WriteLine("TX3:  " + (double)TRANS_MONITOR_VALUES[35] / 10000 + "mW");
                Console.WriteLine("TX4:  " + (double)TRANS_MONITOR_VALUES[36] / 10000 + "mW");
                Console.WriteLine("TX5:  " + (double)TRANS_MONITOR_VALUES[37] / 10000 + "mW");
                Console.WriteLine("TX6:  " + (double)TRANS_MONITOR_VALUES[38] / 10000 + "mW");
                Console.WriteLine("TX7:  " + (double)TRANS_MONITOR_VALUES[39] / 10000 + "mW");
                Console.WriteLine("TX8:  " + (double)TRANS_MONITOR_VALUES[40] / 10000 + "mW");
                Console.WriteLine("TX9:  " + (double)TRANS_MONITOR_VALUES[41] / 10000 + "mW");
                Console.WriteLine("TX10:  " + (double)TRANS_MONITOR_VALUES[42] / 10000 + "mW");
                Console.WriteLine("TX11:  " + (double)TRANS_MONITOR_VALUES[43] / 10000 + "mW");
                Console.WriteLine("TX12:  " + (double)TRANS_MONITOR_VALUES[44] / 10000 + "mW");
                Console.WriteLine("TX13:  " + (double)TRANS_MONITOR_VALUES[45] / 10000 + "mW");
                Console.WriteLine("TX14:  " + (double)TRANS_MONITOR_VALUES[46] / 10000 + "mW");
                Console.WriteLine("TX15:  " + (double)TRANS_MONITOR_VALUES[47] / 10000 + "mW");
                Console.WriteLine("TX-Bias0:  " + TRANS_MONITOR_VALUES[48] * 0.002 + "mA");
                Console.WriteLine("TX-Bias1:  " + TRANS_MONITOR_VALUES[49] * 0.002 + "mA");
                Console.WriteLine("TX-Bias2:  " + TRANS_MONITOR_VALUES[50] * 0.002 + "mA");
                Console.WriteLine("TX-Bias3:  " + TRANS_MONITOR_VALUES[51] * 0.002 + "mA");
                Console.WriteLine("TX-Bias4:  " + TRANS_MONITOR_VALUES[52] * 0.002 + "mA");
                Console.WriteLine("TX-Bias5:  " + TRANS_MONITOR_VALUES[53] * 0.002 + "mA");
                Console.WriteLine("TX-Bias6:  " + TRANS_MONITOR_VALUES[54] * 0.002 + "mA");
                Console.WriteLine("TX-Bias7:  " + TRANS_MONITOR_VALUES[55] * 0.002 + "mA");
                Console.WriteLine("TX-Bias8:  " + TRANS_MONITOR_VALUES[56] * 0.002 + "mA");
                Console.WriteLine("TX-Bias9:  " + TRANS_MONITOR_VALUES[57] * 0.002 + "mA");
                Console.WriteLine("TX-Bias10:  " + TRANS_MONITOR_VALUES[58] * 0.002 + "mA");
                Console.WriteLine("TX-Bias11:  " + TRANS_MONITOR_VALUES[59] * 0.002 + "mA");
                Console.WriteLine("TX-Bias12:  " + TRANS_MONITOR_VALUES[60] * 0.002 + " mA");
                Console.WriteLine("TX-Bias13:  " + TRANS_MONITOR_VALUES[61] * 0.002 + " mA");
                Console.WriteLine("TX-Bias14:  " + TRANS_MONITOR_VALUES[62] * 0.002 + " mA");
                Console.WriteLine("TX-Bias15:  " + TRANS_MONITOR_VALUES[63] * 0.002 + " mA");
                Console.WriteLine("RX0:  " + (double)TRANS_MONITOR_VALUES[64] / 10000 + "mW");
                Console.WriteLine("RX1:  " + (double)TRANS_MONITOR_VALUES[65] / 10000 + "mW");
                Console.WriteLine("RX2:  " + (double)TRANS_MONITOR_VALUES[66] / 10000 + "mW");
                Console.WriteLine("RX3:  " + (double)TRANS_MONITOR_VALUES[67] / 10000 + "mW");
                Console.WriteLine("RX4:  " + (double)TRANS_MONITOR_VALUES[68] / 10000 + "mW");
                Console.WriteLine("RX5:  " + (double)TRANS_MONITOR_VALUES[69] / 10000 + "mW");
                Console.WriteLine("RX6:  " + (double)TRANS_MONITOR_VALUES[70] / 10000 + "mW");
                Console.WriteLine("RX7:  " + (double)TRANS_MONITOR_VALUES[71] / 10000 + "mW");
                Console.WriteLine("RX8:  " + (double)TRANS_MONITOR_VALUES[72] / 10000 + "mW");
                Console.WriteLine("RX9:  " + (double)TRANS_MONITOR_VALUES[73] / 10000 + "mW");
                Console.WriteLine("RX10:  " + (double)TRANS_MONITOR_VALUES[74] / 10000 + "mW");
                Console.WriteLine("RX11:  " + (double)TRANS_MONITOR_VALUES[75] / 10000 + "mW");
                Console.WriteLine("RX12:  " + (double)TRANS_MONITOR_VALUES[76] / 10000 + "mW");
                Console.WriteLine("RX13:  " + (double)TRANS_MONITOR_VALUES[77] / 10000 + "mW");
                Console.WriteLine("RX14:  " + (double)TRANS_MONITOR_VALUES[78] / 10000 + "mW");
                Console.WriteLine("RX15:  " + (double)TRANS_MONITOR_VALUES[79] / 10000 + "mW");



                //////////////////////////////////////////////////////////////////////////////////////////////////////
                //Test Flow 13: Tranceiver control Flow Test Flow 14:noise,PM, FM, AM flow 

                bool ENBALED = false;
                //enable disable shallowLoopBack
                //Console.WriteLine("mlbertmgr_setShallowLoopback status: " + MLBERT.mlbertmgr_setShallowLoopback(ENBALED, APPLYCONFIG));


                // Noise configuration
                ENBALED = true;
                APPLYCONFIG = false;
                Console.WriteLine("mlbertmgr_setNoiseStatus status: " + MLBERT.mlbertmgr_setNoiseStatus(ENBALED));

                double NOISELINERATE = 25.78125;
                Console.WriteLine("mlbertmgr_setNoiseLinerate status: " + MLBERT.mlbertmgr_setNoiseLinerate(ref NOISELINERATE, APPLYCONFIG));

                bool STATUS = true;
                AMPLITUDE = 10;
                double BURSTRATE = 25.78125;
                double ACTUALRATE = 0;
                // Creates PatternConfig initial struct
                PatternConfig NOISETXPATTERN = new PatternConfig();
                // Tx Pattern                                       
                NOISETXPATTERN.pattern = BERTMGR_PATTERNTYPE.BERTMGR_PRBS7;
                // Tx Invert 
                NOISETXPATTERN.invert = false;
                int NOISELEVEL = 20;
                bool isCalibrated = false;

                for (int channel = 0; channel < NB_CHANNELS; channel++)
                {
                    Console.WriteLine("mlbertmgr_enableNoise status: " + MLBERT.mlbertmgr_enableNoise(channel, STATUS));

                    if (isCalibrated)
                    {
                        int NOISEAMPLITUDEMV = 16;
                        Console.WriteLine("mlbertmgr_setNoiseAmplitude_mV status " + MLBERT.mlbertmgr_setNoiseAmplitude_mV(channel, NOISEAMPLITUDEMV, APPLYCONFIG));
                    }
                    else
                    {
                        if (NOISETXPATTERN.pattern != BERTMGR_PATTERNTYPE.BERTMGR_USERDEFINED)
                        {
                            Console.WriteLine("mlbertmgr_setNoiseBurstRate status: " + MLBERT.mlbertmgr_setNoiseBurstRate(channel, BURSTRATE, ref ACTUALRATE));
                        }
                        else
                        {
                            Console.WriteLine("mlbertmgr_setNoiseLevel status: " + MLBERT.mlbertmgr_setNoiseLevel(channel, NOISELEVEL, APPLYCONFIG));
                        }
                    }

                    Console.WriteLine("mlbertmgr_setNoiseTxPattern status: " + MLBERT.mlbertmgr_setNoiseTxPattern(channel, NOISETXPATTERN));
                }
                // PM configuration
                //ushort PMPHASESHIFTAMPLITUDE = 200;
                //Console.WriteLine("mlbertmgr_setPMPhaseShift status: " + MLBERT.mlbertmgr_setPMPhaseShift(PMPHASESHIFTAMPLITUDE, APPLYCONFIG));

                //ushort PMFREQUENCY = 100; //PMFREQUENCY in KHz
                //Console.WriteLine("mlbertmgr_setPMFrequency status: " + MLBERT.mlbertmgr_setPMFrequency(PMFREQUENCY, APPLYCONFIG));

                //STATUS = true;
                //APPLYCONFIG = true;
                //Console.WriteLine("mlbertmgr_enablePM status: " + MLBERT.mlbertmgr_enablePMSJ(STATUS, APPLYCONFIG));

                //ushort PMAMPLITUDE = 100; //V
                //Console.WriteLine("mlbertmgr_setPMAmplitude_ps status: " + MLBERT.mlbertmgr_setPMSJAmplitude_ps(PMAMPLITUDE, APPLYCONFIG));

                //STATUS = true;
                //Console.WriteLine("mlbertmgr_enablePMRJ status: " + MLBERT.mlbertmgr_enablePMRJ(STATUS, APPLYCONFIG));

                //ushort PMRJAMPLITUDE = 2050;
                //Console.WriteLine("mlbertmgr_setPMRJAmplitude status: " + MLBERT.mlbertmgr_setPMRJAmplitude(PMRJAMPLITUDE, APPLYCONFIG));

                //ushort PMPRBBSAMPLITUDE = 2050;
                //Console.WriteLine("mlbertmgr_setPMBUJAmplitude " + MLBERT.mlbertmgr_setPMBUJAmplitude(PMPRBBSAMPLITUDE, APPLYCONFIG));


                //// FM configuration
                //ushort FMPHASESHIFT = 665;
                //Console.WriteLine("mlbertmgr_setFMPhaseShift status: " + MLBERT.mlbertmgr_setFMPhaseShift(FMPHASESHIFT, APPLYCONFIG));

                //ushort FMFREQUENCY = 100;
                //Console.WriteLine("mlbertmgr_setFMFrequency status: " + MLBERT.mlbertmgr_setFMFrequency(FMFREQUENCY, APPLYCONFIG));

                //STATUS = true;
                //APPLYCONFIG = true;
                //Console.WriteLine("mlbertmgr_enableFM status: " + MLBERT.mlbertmgr_enableFMSJ(STATUS, APPLYCONFIG));

                //int FMAMPLITUDE = 22;
                //Console.WriteLine("mlbertmgr_setFMAmplitude_ps status: " + MLBERT.mlbertmgr_setFMSJAmplitude_ps(FMAMPLITUDE, APPLYCONFIG));

                //STATUS = true;
                //Console.WriteLine("mlbertmgr_enableFMRJ status: " + MLBERT.mlbertmgr_enableFMRJ(STATUS, APPLYCONFIG));

                //ushort FMRJAMPLITUDE = 22;
                //Console.WriteLine("mlbertmgr_setFMRJAmplitude status: " + MLBERT.mlbertmgr_setFMRJAmplitude(FMRJAMPLITUDE, APPLYCONFIG));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            finally
            {

                // Disconnect
                MLBERT.mlbertmgr_closeConnection();
                Console.WriteLine("diconnected");
                // destroyInstance
                MLBERT.mlbertmgr_destroyInstance();
                Console.ReadKey();
            }
        }
    }

}
